home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.c++
- Path: nntp.coast.net!torn!sq!news
- From: willer@carolian.com (Steve Willer)
- Subject: Re: Microsoft Visual C++ vs. Borland C++
- Message-ID: <315c2fff.72171602@sqarc.sq.com>
- Sender: news@sq.com (News Administrator)
- Organization: Carolian Systems, Toronto ON
- X-Newsreader: Forte Agent .99d/32.182
- References: <4iria4$i76@granite.sentex.net> <4is07r$9cc@news1.h1.usa.pipeline.com> <4jacau$ibg@comet.magicnet.net>
- Date: Fri, 29 Mar 1996 21:26:36 GMT
-
- catello@magicnet.net (Michael Catello) wrote:
-
- >What makes OWL more object-oriented? I haven't used Borland's products
- >in a couple of years but have been real happy with MSVC. (Borland
- >really pissed me off once; I had been using BC++ for a while, and they
- >had a big push for their ObjectVision product which they marketed to
- >developers. I purchased it when a Borland Salesperson called me and a
- >month later they dropped the product. This was enuf to completely turn
- >me off on the company).
-
- Well, certainly, Borland has made some PR mistakes in the past, and
- it's annoyed quite a lot of customers. However, they do have a new
- policy of actually reporting bugs, which I hope is part of a new
- direction in their customer service.
-
- As for OWL vs. MFC, I find that it is quite a bit more OO than MFC in
- the sense that it is far more polymorphic and abstract. OWL makes use
- of multiple-inheritance in appropriate classes, its container classes
- don't depend on a Smalltalk-style. MFC functions tend to be nothing
- more than wrappers around WIN SDK functions, with the same naming and
- parameters, which I never liked because not only is the SDK not C++,
- it's poorly designed at that.
-
- We don't have MSVC4 here, but I do have some legacy code that uses MFC
- 2, compiled with BC++. An example of the kinds of differences I'm
- talking about are TDC vs. CDC. TDC is written as a true
- resource-cleaning class, in that when you create it, it remembers the
- handles of the stock objects it started with. So, if you call
- something like myDC.SelectObject(myBrush), it will automatically clean
- up. Plus, SelectObject is overridden for each TBitmap, TBrush, etc.,
- and it takes a reference to the object rather than a pointer.
-
- Anyway, here's some simple code, grabbed from my legacy app, written
- in MFC2:
-
- // Dc is a "CDC*" parameter
- CDC dcMem;
- Dc->CreateCompatibleDC(&dcMem);
- CBrush *fillbrush,*oldbrush;
- fillbrush = new CBrush(GetSysColor(COLOR_BTNFACE));
- oldbrush = dcMem.SelectObject(fillbrush);
- // do some drawing
- dcMem.SelectObject(oldbrush);
- delete fillbrush;
-
- There are many things that are done here that are completely
- unnecessary and in fact are dangerous. For one, I don't understand why
- it takes pointers instead of references, since NULL parameters are not
- legal here. But that's a minor issue.
-
- The bigger issue here is that, just like the Win API, the programmer
- is required to select the original brush back into the DC before
- destroying the DC. There is no reason for MFC to require this, as
- evidenced by the fact that OWL doesn't. Plus, why do CDC::Delete() and
- CGDIObject:DeleteObject() even exist as public functions? This only
- serves to further blur the encapsulation of GDI objects. Does a CBrush
- instance represent a "Windows brush"? Does it represent zero? That's
- not clear. And what about that CreateCompatibleDC function? I'm
- obviously not creating a new CDC, because I'm giving it one that it's
- modifying. So what am I creating? Well, it turns out I am creating a
- new "Windows DC", but not a new CDC. This, again, blurs the
- encapsulation of the GDI object, making the code further confused.
- Plus, the SelectObject() function returns a _pointer_ to a brand-new
- TBrush! It is not at all clear by the semantics of the function
- whether the client code should delete this object!
-
- It seems to me to be much clearer to have a CBrush represent a single
- Windows brush, and to have a single CDC represent a single DC. Plus,
- the DC should be able to completely clean up after itself -- that's
- why God gave us constructors and destructors. And why the
- CreateCompatibleDC? Why not use a single-argument constructor? And, of
- course, why does CreateCompatibleDC() take a pointer to DC when it
- doesn't allow a NULL value?
-
- Anyway, here's equivalent code in OWL.
-
- // rDC is a "TDC&" parameter
- TMemDC MemDC(rDC);
- CBrush FillBrush(::GetSysColor(COLOR_BTNFACE));
- MemDC.SelectObject(FillBrush);
- // do some stuff
-
- That's it! Not only is the code shorter, it's more concise. Plus, it
- comes closer to the ideal of "self-documenting code" because more of
- the code is directly related to the purpose of the function (drawing
- some stuff) and none of it is related to cleaning up. Plus, there are
- no opportunities for the developer to forget to clean something up.
-
- And guess what the other great thing about this is? It's _exception
- safe_! Because OWL uses self-contained classes that clean up after
- themselves, I don't need to worry about a thrown exception causing my
- program to leak resources.
-
- >>I guess you mean onus. I think that learning the langugage *is*
- >>the reponsibility of the individual. Microsoft may make the
- >>development of Windows applications easier, but for learning
- >>the language, this "easiness" can actually be detrimental. It's
- >>easy for me to picture someone with a year or more development
- >>experience with MSVC++ but having only a shallow knowledge of
- >>the C++ language itself.
- >
- >I get the impression that you think that making development easier is
- >a bad thing. There will always be bad programmers who never experiment
- >with the language and try to extend their experiences and learning,
- >but who are just out to get the job done (much to the chagrin of those
- >of us that have to go in after as cleanup). These people can never be
- >saved or helped by even the most pure of environments. But for the
- >rest of us, making development easier for the redundant tasks that
- >were all too common in old Win SDK days is like manna from heaven.
-
- I don't think that's what the original poster is referring to. I've
- found that one of the easiest ways to make a project late and of poor
- quality is to forget the long-term and go for the instant
- gratification. I recently read through a book on development
- management written by the Visual C++ product manager, and I was
- appalled at his attitude about C++ (although the book itself was
- well-written and informative, and I would recommend it -- I just don't
- recommend the compiler). His claim was that giving up-to-date C++
- support wasn't worth it because most people weren't actually
- programming in C++ at the time. So they chose to create their
- AppWizards and stuff, which is a great idea, but they completely
- forgot about the part that comes after using AppWizard -- the
- developer-written code.
-
- This is a typical short-term view on things that I strongly disagree
- with. When a developer writes code, when someone designs a program,
- when tests are designed for the product, it is absolutely vital to
- consider the long-term viability and maintainability of the product.
- This not only helps maintenance of the product in the future -- it
- promotes clean code that will have less bugs during development, and
- the remaining bugs will be easier to fix. Microsoft's attitude, which
- seems to be to push the "bleeding-edge" Windows APIs while dismissing
- the practical value of C++ features like templates, exceptions,
- polymorphism and exceptions, is in my view a sure-fire recipe for bugs
- that could have been avoided with a cleaner library design.
-
- Of course, Microsoft's doing pretty well with their compiler, and as
- long as I can still use BC++, I'm happy for them. But I'm not going to
- make a decision on a compiler for myself based on what's best for
- Microsoft. I have to think of myself and my colleagues and what's best
- for us. Of course, what's best for us is code that we won't have to
- worry too much about.
-